import React, { useEffect, useState, useRef } from "react";
import {
  portfolioSummary as mockPortfolioSummary,
  positions as mockPositions,
  marketSnapshot as mockMarketSnapshot,
  Position,
  MarketItem
} from "../mockData";
import {
  fetchDemoMarket,
  fetchDemoPortfolio,
  fetchDemoOrders,
  createDemoOrder,
  DemoOrderRecord,
  DemoOrderSide
} from "../api/demo";
import { getAllMarketQuotes, StockQuote } from "../api/market";
import { getGameTime, GameTimeState } from "../api/gameTime";
import { GameTimeControl } from "./GameTimeControl";
import { StockChart } from "./StockChart";
import { ErrorBoundary } from "./ErrorBoundary";

const cardStyle: React.CSSProperties = {
  padding: "16px 18px",
  borderRadius: "16px",
  border: "1px solid rgba(148,163,184,0.35)",
  background:
    "linear-gradient(135deg, rgba(15,23,42,0.96), rgba(15,23,42,0.7))",
  boxShadow: "0 18px 40px rgba(15,23,42,0.7)"
};

const labelStyle: React.CSSProperties = {
  fontSize: 12,
  color: "#9ca3af"
};

const valueStyle: React.CSSProperties = {
  fontSize: 20,
  fontWeight: 600,
  letterSpacing: "0.04em"
};

const formatCurrency = (value: number) =>
  value.toLocaleString("zh-CN", {
    style: "currency",
    currency: "CNY",
    maximumFractionDigits: 2
  });

const formatPercent = (value: number) =>
  `${value > 0 ? "+" : ""}${value.toFixed(2)}%`;

type PricePoint = {
  t: number;
  price: number;
  volume?: number;
};

// 将 StockQuote 转换为 MarketItem
const quoteToMarketItem = (quote: StockQuote): MarketItem => ({
  symbol: quote.symbol,
  name: quote.name,
  lastPrice: quote.lastPrice,
  changePercent: quote.changePercent,
  volume: quote.volume,
});

const Dashboard: React.FC = () => {
  const [summary, setSummary] = useState(mockPortfolioSummary);
  const [positionsState, setPositionsState] = useState<Position[]>(mockPositions);
  const [marketState, setMarketState] =
    useState<MarketItem[]>(mockMarketSnapshot);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [orderSymbol, setOrderSymbol] = useState<string>("TT-BANK");
  const [orderQuantity, setOrderQuantity] = useState<string>("100");
  const [orderSide, setOrderSide] = useState<DemoOrderSide>("buy");
  const [orderType, setOrderType] = useState<"market" | "limit">("market");
  const [orderStatus, setOrderStatus] = useState<string | null>(null);
  const [orderLoading, setOrderLoading] = useState(false);
  const [orders, setOrders] = useState<DemoOrderRecord[]>([]);
  const [selectedSymbol, setSelectedSymbol] = useState<string>("TT-BANK");
  // 为每个股票维护独立的数据历史（固定240个位置，对应9:30-15:00的交易时间段）
  const [priceSeriesMap, setPriceSeriesMap] = useState<Map<string, (PricePoint | null)[]>>(new Map());
  // 为每个股票维护上一次的总成交量（用于计算增量成交量）
  const lastTotalVolumeMapRef = useRef<Map<string, number>>(new Map());
  // 为每个股票维护每个时间索引位置的累计成交量基准值（用于正确计算增量）
  const timeIndexVolumeMapRef = useRef<Map<string, Map<number, number>>>(new Map());
  // 为每个股票维护当日开盘时间（用于计算时间索引）
  const tradingDayStartRef = useRef<Map<string, Date>>(new Map());
  const pollingRef = useRef<number | null>(null);
  const [chartMode, setChartMode] = useState<"intraday" | "kline">("intraday");
  const [now, setNow] = useState<Date>(new Date());
  const [gameTimeState, setGameTimeState] = useState<{ gameDate: string; isTradingHours: boolean } | null>(null);
  
  // 获取当前选中股票的数据（保持固定大小240，null值表示该时间点暂无数据）
  const priceSeries = priceSeriesMap.get(selectedSymbol) || new Array(240).fill(null);

  useEffect(() => {
    let cancelled = false;
    const load = async () => {
      try {
        // 尝试使用真实的 market API，失败则回退到 demo API
        let marketQuotes: StockQuote[] = [];
        try {
          marketQuotes = await getAllMarketQuotes();
        } catch (marketError) {
          console.warn("Market API 不可用，使用 demo API:", marketError);
          // 如果 market API 失败，尝试使用 demo API
          const marketRes = await fetchDemoMarket();
          // 将 demo 数据转换为 StockQuote 格式（缺少涨跌幅和成交量）
          marketQuotes = marketRes.items.map((m) => ({
            symbol: m.symbol,
            name: m.name,
            lastPrice: m.lastPrice,
            openPrice: m.lastPrice,
            highPrice: m.lastPrice,
            lowPrice: m.lastPrice,
            volume: 0,
            change: 0,
            changePercent: 0,
            timestamp: new Date().toISOString(),
          }));
        }

        const [portfolioRes, ordersRes] = await Promise.all([
          fetchDemoPortfolio(),
          fetchDemoOrders(),
        ]);
        if (cancelled) return;

        const totalValue = portfolioRes.totalValue;
        const cash = portfolioRes.cash;
        const dailyPnl = totalValue * 0.01;

        setSummary({
          totalValue,
          cash,
          dailyPnl,
          dailyPnlPercent: 1,
        });

        setPositionsState(
          portfolioRes.positions.map((p) => ({
            symbol: p.symbol,
            name: p.name,
            quantity: p.quantity,
            avgPrice: p.avgPrice,
            lastPrice: p.lastPrice,
          })),
        );

        // 使用真实的 market API 数据
        setMarketState(marketQuotes.map(quoteToMarketItem));

        setOrders(ordersRes.items);

        setError(null);
      } catch (e) {
        // 失败则保持 mock 数据，并提示错误
        console.error(e);
        if (!cancelled) {
          setError("后端未启动或接口不可用，当前展示的是本地假数据。");
        }
      } finally {
        if (!cancelled) {
          setLoading(false);
        }
      }
    };
    load();
    return () => {
      cancelled = true;
    };
  }, []);

  // 顶部右上角系统时间
  useEffect(() => {
    const id = window.setInterval(() => setNow(new Date()), 1000);
    return () => window.clearInterval(id);
  }, []);

  // 获取游戏时间（用于计算时间索引）
  useEffect(() => {
    const fetchGameTime = async () => {
      try {
        const gameTime = await getGameTime();
        setGameTimeState({
          gameDate: gameTime.gameDate,
          isTradingHours: gameTime.isTradingHours,
        });
      } catch (e) {
        console.error("获取游戏时间失败", e);
      }
    };
    fetchGameTime();
    const id = setInterval(fetchGameTime, 5000); // 每5秒更新一次游戏时间
    return () => clearInterval(id);
  }, []);

  // 计算时间索引：根据游戏时间计算在交易时间段（9:30-15:00）中的位置
  const calculateTimeIndex = (gameTimeStr: string, symbol: string): number | null => {
    try {
      const gameDate = new Date(gameTimeStr);
      const hour = gameDate.getHours();
      const minute = gameDate.getMinutes();
      
      // 交易时间段：9:30-15:00
      const startHour = 9;
      const startMinute = 30;
      const endHour = 15;
      const endMinute = 0;
      
      // 交易时间段总分钟数：330分钟
      const totalMinutes = (endHour - startHour) * 60 + (endMinute - startMinute);
      const MAX_POINTS = 240;
      
      // 计算从9:30开始的分钟数（允许超出范围，但会被限制在0-239）
      let minutesFromStart = (hour - startHour) * 60 + (minute - startMinute);
      
      // 如果时间早于9:30，设为0
      if (minutesFromStart < 0) {
        minutesFromStart = 0;
      }
      // 如果时间晚于15:00，设为最大值
      if (minutesFromStart > totalMinutes) {
        minutesFromStart = totalMinutes;
      }
      
      // 映射到240个位置（0-239，与时间标签生成逻辑一致）
      // 使用 MAX_POINTS - 1 来保持与时间标签生成的一致性（ratio = i / (count - 1)）
      const index = Math.floor((minutesFromStart / totalMinutes) * (MAX_POINTS - 1));
      return Math.min(Math.max(0, index), MAX_POINTS - 1);
    } catch (e) {
      console.error("计算时间索引失败", e);
      return null;
    }
  };

  // 实时轮询行情，更新当前选中标的的分时 & K 线数据
  useEffect(() => {
    if (pollingRef.current !== null) {
      window.clearInterval(pollingRef.current);
      pollingRef.current = null;
    }

    const tick = async () => {
      try {
        // 获取游戏时间
        let currentGameTime: GameTimeState | null = null;
        try {
          currentGameTime = await getGameTime();
          setGameTimeState({
            gameDate: currentGameTime.gameDate,
            isTradingHours: currentGameTime.isTradingHours,
          });
        } catch (e) {
          console.warn("获取游戏时间失败", e);
        }
        
        // 使用真实的 market API 获取最新行情
        let marketQuotes: StockQuote[] = [];
        let useRealAPI = true;
        
        try {
          marketQuotes = await getAllMarketQuotes();
        } catch (marketError) {
          console.warn("Market API 轮询失败，尝试 demo API:", marketError);
          useRealAPI = false;
          // 如果 market API 失败，回退到 demo API
          const marketRes = await fetchDemoMarket();
          // 将 demo 数据转换为 StockQuote 格式
          marketQuotes = marketRes.items.map((m) => ({
            symbol: m.symbol,
            name: m.name,
            lastPrice: m.lastPrice,
            openPrice: m.lastPrice,
            highPrice: m.lastPrice,
            lowPrice: m.lastPrice,
            volume: 0,
            change: 0,
            changePercent: 0,
            timestamp: new Date().toISOString(),
          }));
        }

        // 更新股票列表数据
        setMarketState(marketQuotes.map(quoteToMarketItem));

        // 更新所有股票的数据（根据时间索引映射到对应位置）
        setPriceSeriesMap((prevMap) => {
          const newMap = new Map(prevMap);
          const MAX_POINTS = 240;
          
          marketQuotes.forEach((quote) => {
            const symbol = quote.symbol;
            
            // 初始化或获取固定大小的数组
            let seriesArray = newMap.get(symbol);
            if (!seriesArray || seriesArray.length !== MAX_POINTS) {
              seriesArray = new Array(MAX_POINTS).fill(null);
              newMap.set(symbol, seriesArray);
            }
            
            // 计算时间索引（根据游戏时间映射到交易时间段的对应位置）
            let timeIndex: number | null = null;
            
            if (currentGameTime) {
              timeIndex = calculateTimeIndex(currentGameTime.gameDate, symbol);
            }
            
            // 如果无法计算时间索引，使用当前时间的分钟数作为fallback
            if (timeIndex === null) {
              const now = new Date();
              const hour = now.getHours();
              const minute = now.getMinutes();
              // 使用当前时间计算相对位置（与时间标签生成逻辑一致）
              const startHour = 9;
              const startMinute = 30;
              const totalMinutes = (15 - 9) * 60 - 30; // 330分钟
              let minutesFromStart = (hour - startHour) * 60 + (minute - startMinute);
              if (minutesFromStart < 0) minutesFromStart = 0;
              if (minutesFromStart > totalMinutes) minutesFromStart = totalMinutes;
              // 使用 (MAX_POINTS - 1) 保持与时间标签生成的一致性
              timeIndex = Math.min(Math.max(0, Math.floor((minutesFromStart / totalMinutes) * (MAX_POINTS - 1))), MAX_POINTS - 1);
            }
            
            if (timeIndex === null || timeIndex < 0 || timeIndex >= MAX_POINTS) {
              console.warn(`时间索引计算失败: ${timeIndex}, symbol: ${symbol}`);
              return;
            }
            
            // 获取上一个价格（用于计算增量成交量）
            const prevData = seriesArray[timeIndex];
            const prevPrice = prevData?.price || quote.lastPrice;
            const priceChange = Math.abs(quote.lastPrice - prevPrice);
            
            // 计算增量成交量（当前时刻的成交量，不是累计值）
            let volume: number;
            if (useRealAPI && quote.volume > 0) {
              const currentTotalVolume = quote.volume;
              
              // 获取该时间索引位置的累计成交量基准值
              let symbolTimeIndexMap = timeIndexVolumeMapRef.current.get(symbol);
              if (!symbolTimeIndexMap) {
                symbolTimeIndexMap = new Map();
                timeIndexVolumeMapRef.current.set(symbol, symbolTimeIndexMap);
              }
              
              const baseVolumeAtTimeIndex = symbolTimeIndexMap.get(timeIndex);
              const lastTotalVolume = lastTotalVolumeMapRef.current.get(symbol) || 0;
              
              // 如果之前在同一时间位置已经有数据
              if (prevData !== null && prevData !== undefined) {
                // 时间索引没变，说明还在同一时间点
                // 如果累计成交量有增长，累加增量；否则保持原值
                if (baseVolumeAtTimeIndex !== undefined && currentTotalVolume > baseVolumeAtTimeIndex) {
                  // 该时间点累计成交量有增长，累加增量
                  const prevVolume = prevData.volume || 0;
                  const volumeIncrement = currentTotalVolume - baseVolumeAtTimeIndex;
                  volume = prevVolume + volumeIncrement;
                  // 更新基准值
                  symbolTimeIndexMap.set(timeIndex, currentTotalVolume);
                } else {
                  // 累计成交量没有增长（后端还没更新），保持原值
                  volume = prevData.volume || 0;
                }
              } else {
                // 新的时间位置，计算从上次总成交量到现在的增量
                const volumeIncrement = Math.max(0, currentTotalVolume - lastTotalVolume);
                volume = volumeIncrement;
                // 记录这个时间索引位置的累计成交量基准值（刚进入时）
                if (baseVolumeAtTimeIndex === undefined) {
                  symbolTimeIndexMap.set(timeIndex, lastTotalVolume);
                }
                // 更新基准值为当前值
                symbolTimeIndexMap.set(timeIndex, currentTotalVolume);
              }
              
              // 更新上一次总成交量（用于下次计算新时间位置的增量）
              lastTotalVolumeMapRef.current.set(symbol, currentTotalVolume);
            } else {
              // 模拟成交量：基于价格变化计算这一时刻的成交量
              if (prevData !== null && prevData !== undefined) {
                // 如果已有数据，累加一些随机成交量
                const prevVolume = prevData.volume || 0;
                volume = prevVolume + Math.floor(Math.random() * 5000);
              } else {
                volume = Math.floor(10000 + priceChange * 10000 + Math.random() * 5000);
              }
            }
            
            // 更新对应时间位置的数据
            const next: PricePoint = {
              t: currentGameTime ? new Date(currentGameTime.gameDate).getTime() : Date.now(),
              price: quote.lastPrice,
              volume: volume,
            };
            
            // 在对应时间位置更新数据
            seriesArray[timeIndex] = next;
            newMap.set(symbol, [...seriesArray]);
          });
          
          return newMap;
        });
      } catch (e) {
        console.error("poll market failed", e);
      }
    };

    // 立即拉一次，然后每 3 秒刷新
    tick();
    const id = window.setInterval(tick, 3000);
    pollingRef.current = id;

    return () => {
      if (pollingRef.current !== null) {
        window.clearInterval(pollingRef.current);
        pollingRef.current = null;
      }
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [selectedSymbol]);

  const pnlColor = summary.dailyPnl >= 0 ? "#22c55e" : "#ef4444";

  const handleQuickOrder = async () => {
    const quantityNum = Number(orderQuantity);
    if (!orderSymbol || Number.isNaN(quantityNum) || quantityNum <= 0) {
      setOrderStatus("请输入有效的数量。");
      return;
    }
    setOrderLoading(true);
    setOrderStatus(null);
    try {
      await createDemoOrder({
        symbol: orderSymbol,
        quantity: quantityNum,
        side: orderSide
      });
      setOrderStatus(
        orderSide === "buy"
          ? "买入成功（demo），资产已更新。"
          : "卖出成功（demo），资产已更新。"
      );

      const [portfolioRes, marketRes, ordersRes] = await Promise.all([
        fetchDemoPortfolio(),
        fetchDemoMarket(),
        fetchDemoOrders()
      ]);

      const totalValue = portfolioRes.totalValue;
      const cash = portfolioRes.cash;
      const dailyPnl = totalValue * 0.01;

      setSummary({
        totalValue,
        cash,
        dailyPnl,
        dailyPnlPercent: 1
      });

      setPositionsState(
        portfolioRes.positions.map((p) => ({
          symbol: p.symbol,
          name: p.name,
          quantity: p.quantity,
          avgPrice: p.avgPrice,
          lastPrice: p.lastPrice
        }))
      );

      setMarketState(
        marketRes.items.map((m) => ({
          symbol: m.symbol,
          name: m.name,
          lastPrice: m.lastPrice,
          changePercent: 0,
          volume: 0
        }))
      );

      setOrders(ordersRes.items);
    } catch (e) {
      console.error(e);
      setOrderStatus(
        e instanceof Error ? e.message : "下单失败，请检查后端 demo 服务。"
      );
    } finally {
      setOrderLoading(false);
    }
  };

  return (
    <div
      style={{
        minHeight: "100vh",
        background:
          "radial-gradient(circle at top, #0f172a 0, #020617 45%, #000 100%)",
        color: "#e5e7eb",
        fontFamily:
          "-apple-system, BlinkMacSystemFont, system-ui, -system-ui, sans-serif"
      }}
    >
      <div
        style={{
          maxWidth: 1120,
          margin: "0 auto",
          padding: "24px 20px 32px"
        }}
      >
        <header
          style={{
            display: "flex",
            justifyContent: "space-between",
            alignItems: "center",
            marginBottom: 24
          }}
        >
          <div>
            <div
              style={{
                fontSize: 12,
                textTransform: "uppercase",
                letterSpacing: "0.16em",
                color: "#6b7280",
                marginBottom: 4
              }}
            >
              TraderTycoon · 金融大亨
            </div>
            <h1
              style={{
                fontSize: 22,
                margin: 0,
                fontWeight: 600,
                letterSpacing: "0.04em"
              }}
            >
              初始资产仪表盘
            </h1>
            <p
              style={{
                margin: "6px 0 0",
                fontSize: 13,
                color: "#9ca3af"
              }}
            >
              当前会优先尝试请求后端 demo 接口，若不可用则自动回退到本地假数据。
            </p>
          </div>
          <div
            style={{
              fontSize: 12,
              color: "#9ca3af",
              textAlign: "right"
            }}
          >
            <div>
              游戏日历：2035-06-21 · 服务器：模拟环境 DEV
            </div>
            <div>
              系统时间：{" "}
              {now.toLocaleString("zh-CN", {
                hour12: false
              })}
            </div>
            {loading ? (
              <div style={{ marginTop: 4 }}>正在拉取 demo 数据…</div>
            ) : null}
          </div>
        </header>

        <section
          style={{
            display: "grid",
            gridTemplateColumns: "repeat(3, minmax(0, 1fr))",
            gap: 16,
            marginBottom: 24
          }}
        >
          <div style={cardStyle}>
            <div style={labelStyle}>总资产（含持仓）</div>
            <div style={{ ...valueStyle, marginTop: 6 }}>
              {formatCurrency(summary.totalValue)}
            </div>
          </div>
          <div style={cardStyle}>
            <div style={labelStyle}>可用现金</div>
            <div style={{ ...valueStyle, marginTop: 6 }}>
              {formatCurrency(summary.cash)}
            </div>
          </div>
          <div style={cardStyle}>
            <div style={labelStyle}>当日盈亏</div>
            <div
              style={{
                ...valueStyle,
                marginTop: 6,
                color: pnlColor,
                display: "flex",
                alignItems: "baseline",
                gap: 8
              }}
            >
              <span>
                {summary.dailyPnl >= 0 ? "+" : "-"}
                {formatCurrency(Math.abs(summary.dailyPnl))}
              </span>
              <span
                style={{
                  fontSize: 13,
                  padding: "2px 8px",
                  borderRadius: 999,
                  border: `1px solid ${pnlColor}40`,
                  backgroundColor: "#020617"
                }}
              >
                {formatPercent(summary.dailyPnlPercent)}
              </span>
            </div>
          </div>
        </section>

        {/* 游戏时间控制 */}
        <section style={{ marginBottom: 24 }}>
          <GameTimeControl />
        </section>

        {/* 中央主区域：左侧图表，右侧股票列表 + 下单 */}
        <section
          style={{
            display: "grid",
            gridTemplateColumns: "minmax(0, 7fr) minmax(260px, 3fr)",
            gap: 16
          }}
        >
          <div style={cardStyle}>
            <div
              style={{
                display: "flex",
                justifyContent: "space-between",
                alignItems: "center",
                marginBottom: 8
              }}
            >
              <SectionHeader
                title={`价格走势 · ${selectedSymbol}`}
                subtitle="可在右侧列表选择标的，上方分时图 / 下方 K 线图"
              />
              <div
                style={{
                  display: "inline-flex",
                  borderRadius: 999,
                  border: "1px solid rgba(148,163,184,0.6)",
                  overflow: "hidden",
                  fontSize: 12
                }}
              >
                <button
                  type="button"
                  onClick={() => setChartMode("intraday")}
                  style={{
                    padding: "4px 10px",
                    border: "none",
                    cursor: "pointer",
                    backgroundColor:
                      chartMode === "intraday" ? "#e5e7eb" : "transparent",
                    color: chartMode === "intraday" ? "#020617" : "#e5e7eb"
                  }}
                >
                  分时
                </button>
                <button
                  type="button"
                  onClick={() => setChartMode("kline")}
                  style={{
                    padding: "4px 10px",
                    border: "none",
                    cursor: "pointer",
                    backgroundColor:
                      chartMode === "kline" ? "#e5e7eb" : "transparent",
                    color: chartMode === "kline" ? "#020617" : "#e5e7eb"
                  }}
                >
                  K 线
                </button>
              </div>
            </div>
            <ErrorBoundary>
              <StockChart
                series={priceSeries}
                mode={chartMode}
                width={600}
                height={300}
                showVolume={true}
              />
            </ErrorBoundary>
          </div>

          <div
            style={{
              display: "flex",
              flexDirection: "column",
              gap: 12
            }}
          >
            <div style={cardStyle}>
              <SectionHeader
                title="股票列表"
                subtitle="点击行可切换左侧图表与下单标的"
              />
              <MarketTable
                items={marketState}
                selectedSymbol={selectedSymbol}
                onSelectSymbol={(sym) => {
                  setSelectedSymbol(sym);
                  setOrderSymbol(sym);
                }}
              />
            </div>

            <div style={cardStyle}>
              <SectionHeader
                title="快速下单（demo）"
                subtitle="支持买入/卖出，调用 /api/demo/order 更新资产与持仓"
              />
              <div
                style={{
                  display: "grid",
                  gridTemplateColumns: "repeat(2, 1fr)",
                  gap: "12px 8px",
                  marginBottom: 8,
                  fontSize: 12
                }}
              >
                <label style={{ display: "flex", flexDirection: "column" }}>
                  <span style={{ marginBottom: 4, color: "#9ca3af" }}>
                    标的
                  </span>
                  <select
                    value={orderSymbol}
                    onChange={(e) => {
                      setOrderSymbol(e.target.value);
                      setSelectedSymbol(e.target.value);
                    }}
                    style={{
                      backgroundColor: "#020617",
                      color: "#e5e7eb",
                      borderRadius: 999,
                      border: "1px solid rgba(148,163,184,0.6)",
                      padding: "4px 10px",
                      fontSize: 12,
                      width: "100%",
                      boxSizing: "border-box"
                    }}
                  >
                    {marketState.map((m) => (
                      <option key={m.symbol} value={m.symbol}>
                        {m.symbol} · {m.name}
                      </option>
                    ))}
                  </select>
                </label>

                <label style={{ display: "flex", flexDirection: "column" }}>
                  <span style={{ marginBottom: 4, color: "#9ca3af" }}>
                    方向
                  </span>
                  <select
                    value={orderSide}
                    onChange={(e) =>
                      setOrderSide(e.target.value as DemoOrderSide)
                    }
                    style={{
                      backgroundColor: "#020617",
                      color: "#e5e7eb",
                      borderRadius: 999,
                      border: "1px solid rgba(148,163,184,0.6)",
                      padding: "4px 10px",
                      fontSize: 12,
                      width: "100%",
                      boxSizing: "border-box"
                    }}
                  >
                    <option value="buy">买入</option>
                    <option value="sell">卖出</option>
                  </select>
                </label>

                <label style={{ display: "flex", flexDirection: "column" }}>
                  <span style={{ marginBottom: 4, color: "#9ca3af" }}>
                    数量
                  </span>
                  <input
                    type="number"
                    min={1}
                    value={orderQuantity}
                    onChange={(e) => setOrderQuantity(e.target.value)}
                    style={{
                      backgroundColor: "#020617",
                      color: "#e5e7eb",
                      borderRadius: 999,
                      border: "1px solid rgba(148,163,184,0.6)",
                      padding: "4px 10px",
                      fontSize: 12,
                      width: "100%",
                      boxSizing: "border-box"
                    }}
                  />
                </label>

                <label style={{ display: "flex", flexDirection: "column" }}>
                  <span style={{ marginBottom: 4, color: "#9ca3af" }}>
                    订单类型
                  </span>
                  <select
                    value={orderType}
                    onChange={(e) =>
                      setOrderType(e.target.value as "market" | "limit")
                    }
                    style={{
                      backgroundColor: "#020617",
                      color: "#e5e7eb",
                      borderRadius: 999,
                      border: "1px solid rgba(148,163,184,0.6)",
                      padding: "4px 10px",
                      fontSize: 12,
                      width: "100%",
                      boxSizing: "border-box"
                    }}
                  >
                    <option value="market">市价单</option>
                    <option value="limit">限价单（demo 按市价即时成交）</option>
                  </select>
                </label>
              </div>
              
              <button
                type="button"
                onClick={handleQuickOrder}
                disabled={orderLoading}
                style={{
                  width: "100%",
                  padding: "8px 14px",
                  borderRadius: 999,
                  border: "none",
                  fontSize: 12,
                  fontWeight: 500,
                  cursor: orderLoading ? "default" : "pointer",
                  background:
                    "linear-gradient(135deg, #22c55e, #16a34a, #22c55e)",
                  color: "#020617",
                  opacity: orderLoading ? 0.6 : 1,
                  marginBottom: orderStatus ? 8 : 0
                }}
              >
                {orderLoading ? "下单中…" : "提交订单（demo）"}
              </button>
              
              {orderStatus ? (
                <div
                  style={{
                    fontSize: 12,
                    color: orderStatus.includes("成功") ? "#22c55e" : "#f97316",
                    marginTop: 8
                  }}
                >
                  {orderStatus}
                </div>
              ) : null}
            </div>
          </div>
        </section>
        <section style={{ marginTop: 16 }}>
          <div style={cardStyle}>
            <SectionHeader
              title="当前持仓"
              subtitle="股票 / 航运 / 科技等多元资产组合"
            />
            <PositionsTable items={positionsState} />
          </div>
        </section>
        <section style={{ marginTop: 16 }}>
          <div style={cardStyle}>
            <SectionHeader
              title={`价格走势 · ${selectedSymbol}`}
              subtitle="专业图表展示，支持分时图和K线图切换"
            />
            <ErrorBoundary>
              <StockChart
                series={priceSeries}
                mode={chartMode}
                width={1056}
                height={400}
                showVolume={true}
              />
            </ErrorBoundary>
          </div>
        </section>
        <section style={{ marginTop: 16 }}>
          <div style={cardStyle}>
            <SectionHeader
              title="订单历史（demo）"
              subtitle="最近的买入/卖出记录，来自 /api/demo/orders"
            />
            <OrdersTable items={orders} />
          </div>
        </section>
        {error ? (
          <div
            style={{
              marginTop: 16,
              fontSize: 12,
              color: "#f97316"
            }}
          >
            {error}
          </div>
        ) : null}
      </div>
    </div>
  );
};

const SectionHeader: React.FC<{ title: string; subtitle?: string }> = ({
  title,
  subtitle
}) => (
  <div style={{ marginBottom: 12 }}>
    <div
      style={{
        fontSize: 14,
        fontWeight: 500,
        letterSpacing: "0.04em",
        textTransform: "uppercase"
      }}
    >
      {title}
    </div>
    {subtitle ? (
      <div style={{ fontSize: 12, color: "#9ca3af", marginTop: 2 }}>
        {subtitle}
      </div>
    ) : null}
  </div>
);

const tableBaseStyle: React.CSSProperties = {
  width: "100%",
  borderCollapse: "collapse",
  fontSize: 12
};

const thStyle: React.CSSProperties = {
  textAlign: "left",
  padding: "6px 4px",
  color: "#9ca3af",
  fontWeight: 500,
  borderBottom: "1px solid rgba(55,65,81,0.9)"
};

const tdStyle: React.CSSProperties = {
  padding: "6px 4px",
  borderBottom: "1px solid rgba(31,41,55,0.7)"
};

const PositionsTable: React.FC<{ items: Position[] }> = ({ items }) => (
  <div style={{ overflowX: "auto" }}>
    <table style={tableBaseStyle}>
      <thead>
        <tr>
          <th style={thStyle}>代码</th>
          <th style={thStyle}>名称</th>
          <th style={thStyle}>数量</th>
          <th style={thStyle}>成本价</th>
          <th style={thStyle}>现价</th>
          <th style={thStyle}>浮动盈亏%</th>
        </tr>
      </thead>
      <tbody>
        {items.map((p) => {
          const changePercent = ((p.lastPrice - p.avgPrice) / p.avgPrice) * 100;
          const color = changePercent >= 0 ? "#22c55e" : "#ef4444";
          return (
            <tr key={p.symbol}>
              <td style={tdStyle}>{p.symbol}</td>
              <td style={tdStyle}>{p.name}</td>
              <td style={tdStyle}>{p.quantity.toLocaleString("zh-CN")}</td>
              <td style={tdStyle}>{p.avgPrice.toFixed(2)}</td>
              <td style={tdStyle}>{p.lastPrice.toFixed(2)}</td>
              <td style={{ ...tdStyle, color }}>{formatPercent(changePercent)}</td>
            </tr>
          );
        })}
      </tbody>
    </table>
  </div>
);

const MarketTable: React.FC<{
  items: MarketItem[];
  selectedSymbol?: string;
  onSelectSymbol?: (symbol: string) => void;
}> = ({ items, selectedSymbol, onSelectSymbol }) => (
  <div style={{ overflowX: "auto" }}>
    <table style={tableBaseStyle}>
      <thead>
        <tr>
          <th style={thStyle}>代码</th>
          <th style={thStyle}>名称</th>
          <th style={thStyle}>最新价</th>
          <th style={thStyle}>涨跌幅</th>
          <th style={thStyle}>成交量</th>
        </tr>
      </thead>
      <tbody>
        {items.map((m) => {
          const color = m.changePercent >= 0 ? "#22c55e" : "#ef4444";
          const active = selectedSymbol === m.symbol;
          return (
            <tr
              key={m.symbol}
              onClick={() => onSelectSymbol?.(m.symbol)}
              style={{
                cursor: onSelectSymbol ? "pointer" : "default",
                backgroundColor: active ? "rgba(59,130,246,0.25)" : "transparent"
              }}
            >
              <td style={tdStyle}>{m.symbol}</td>
              <td style={tdStyle}>{m.name}</td>
              <td style={tdStyle}>{m.lastPrice.toFixed(2)}</td>
              <td style={{ ...tdStyle, color }}>
                {formatPercent(m.changePercent)}
              </td>
              <td style={tdStyle}>{m.volume.toLocaleString("zh-CN")}</td>
            </tr>
          );
        })}
      </tbody>
    </table>
  </div>
);

const OrdersTable: React.FC<{ items: DemoOrderRecord[] }> = ({ items }) => (
  <div style={{ overflowX: "auto" }}>
    <table style={tableBaseStyle}>
      <thead>
        <tr>
          <th style={thStyle}>时间</th>
          <th style={thStyle}>代码</th>
          <th style={thStyle}>名称</th>
          <th style={thStyle}>方向</th>
          <th style={thStyle}>数量</th>
          <th style={thStyle}>成交价</th>
          <th style={thStyle}>成交额</th>
        </tr>
      </thead>
      <tbody>
        {items.map((o) => {
          const sideColor = o.side === "buy" ? "#22c55e" : "#ef4444";
          const notional = o.price * o.quantity;
          return (
            <tr key={o.id}>
              <td style={tdStyle}>
                {new Date(o.executedAt).toLocaleTimeString("zh-CN", {
                  hour12: false
                })}
              </td>
              <td style={tdStyle}>{o.symbol}</td>
              <td style={tdStyle}>{o.name}</td>
              <td style={{ ...tdStyle, color: sideColor }}>
                {o.side === "buy" ? "买入" : "卖出"}
              </td>
              <td style={tdStyle}>{o.quantity.toLocaleString("zh-CN")}</td>
              <td style={tdStyle}>{o.price.toFixed(2)}</td>
              <td style={tdStyle}>{notional.toFixed(2)}</td>
            </tr>
          );
        })}
        {items.length === 0 ? (
          <tr>
            <td style={tdStyle} colSpan={7}>
              暂无订单记录。
            </td>
          </tr>
        ) : null}
      </tbody>
    </table>
  </div>
);


export default Dashboard;


